//! Read system call implementation
//! SPDX-License-Identifier: MPL-2.0

const std = @import("std");
const SyscallReturn = @import("../return.zig").SyscallReturn;
const SyscallError = @import("../error.zig").SyscallError;
const Context = @import("../context.zig").Context;
const Fd = @import("../context.zig").Fd;
const VirtAddr = @import("../context.zig").VirtAddr;

/// File interface for reading
const File = struct {
    fd: Fd,
    
    const Self = @This();
    
    /// Read data into a writer
    pub fn read(self: Self, writer: anytype) !usize {
        _ = self;
        _ = writer;
        // TODO: Implement actual file reading
        // This would interface with the VFS layer
        return 0;
    }
    
    /// Read exact number of bytes
    pub fn read_bytes(self: Self, buffer: []u8) !usize {
        _ = self;
        _ = buffer;
        // TODO: Implement actual file reading
        return 0;
    }
};

/// Get file from file descriptor
fn get_file(file_table: anytype, fd: Fd) !File {
    _ = file_table;
    if (fd < 0) {
        return error.BadFileDescriptor;
    }
    // TODO: Implement actual file table lookup
    return File{ .fd = fd };
}

/// Read system call implementation
pub fn sys_read(fd: Fd, user_buf_addr: VirtAddr, buf_len: usize, ctx: *Context) SyscallReturn {
    // Validate file descriptor
    if (fd < 0) {
        return SyscallReturn.error_return(SyscallError.EBADF);
    }
    
    // Get file from file table
    var file_table = ctx.thread_local.borrow_file_table_mut();
    const file = get_file(file_table, fd) catch {
        return SyscallReturn.error_return(SyscallError.EBADF);
    };
    
    // Handle empty buffer case
    if (buf_len == 0) {
        // Just check if the file descriptor is valid
        const read_len = file.read_bytes(&[_]u8{}) catch |err| {
            return SyscallReturn.error_return(map_error(err));
        };
        return SyscallReturn.success(read_len);
    }
    
    // Read data from file
    const user_space = ctx.user_space();
    var writer = user_space.writer(user_buf_addr, buf_len) catch {
        return SyscallReturn.error_return(SyscallError.EFAULT);
    };
    
    const read_len = file.read(&writer) catch |err| {
        return SyscallReturn.error_return(map_error(err));
    };
    
    return SyscallReturn.success(read_len);
}

/// Map internal errors to syscall errors
fn map_error(err: anyerror) SyscallError {
    return switch (err) {
        error.BadFileDescriptor => SyscallError.EBADF,
        error.InvalidAddress => SyscallError.EFAULT,
        error.Interrupted => SyscallError.ERESTARTSYS,
        error.WouldBlock => SyscallError.EAGAIN,
        error.BrokenPipe => SyscallError.EPIPE,
        error.InvalidArgument => SyscallError.EINVAL,
        error.NoSpaceLeft => SyscallError.ENOSPC,
        error.PermissionDenied => SyscallError.EACCES,
        else => SyscallError.EIO,
    };
}